What is defu?
The defu npm package is a utility for performing default deep assignments on objects. It is commonly used to merge a set of objects into a single object, where the properties of later objects will overwrite those of earlier ones if they exist. This is particularly useful for managing configurations or options objects where default values need to be easily overridden by user inputs or other sources.
What are defu's main functionalities?
Deep Object Merging
This feature allows for the deep merging of objects. Properties from the second object (`objB`) are merged into the first object (`objA`), with nested properties being merged rather than replaced. This is useful for combining configurations with nested structures.
{"const defu = require('defu');\nconst objA = { foo: { bar: true } };\nconst objB = { foo: { baz: false }, qux: 1 };\nconst result = defu(objA, objB);\nconsole.log(result); // Output: { foo: { bar: true, baz: false }, qux: 1 }"}
Array Merging
This demonstrates how `defu` can be used to merge arrays contained within objects. Instead of replacing the array in `arrA` with the one in `arrB`, `defu` concatenates the arrays, preserving the order and contents of both.
{"const defu = require('defu');\nconst arrA = { arr: [1, 2] };\nconst arrB = { arr: [3, 4] };\nconst result = defu(arrA, arrB);\nconsole.log(result); // Output: { arr: [1, 2, 3, 4] }"}
Other packages similar to defu
lodash.merge
Lodash's merge function offers similar deep merging capabilities as defu. However, lodash is a much larger library with a wide range of utilities beyond object merging. While defu is focused and lightweight, lodash provides a comprehensive suite of tools that may be beneficial for projects needing more than just object merging.
deepmerge
Deepmerge is another npm package that specializes in merging objects deeply. Like defu, it is focused on this specific task, but it offers more customization options, such as array merging strategies and cloning. This makes deepmerge a more flexible choice for complex merging needs, though it might be slightly more complex to use than defu.
🌊 defu
Assign default properties, recursively. Lightweight and Fast.
Install
Install package:
yarn add defu
npm install defu
pnpm install defu
Usage
import { defu } from "defu";
const options = defu(object, ...defaults);
Leftmost arguments have more priority when assigning defaults.
Arguments
- object (Object): The destination object.
- source (Object): The source object.
import { defu } from "defu";
console.log(defu({ a: { b: 2 } }, { a: { b: 1, c: 3 } }));
Using with CommonJS
const { defu } = require("defu");
Custom Merger
Sometimes default merging strategy is not desirable. Using createDefu
we can create a custom instance with different merging strategy.
This function accepts obj
(source object), key
and value
(current value) and should return true
if applied custom merging.
Example: Sum numbers instead of overriding
import { createDefu } from "defu";
const ext = createDefu((obj, key, value) => {
if (typeof obj[key] === "number" && typeof value === "number") {
obj[key] += value;
return true;
}
});
ext({ cost: 15 }, { cost: 10 });
Function Merger
Using defuFn
, if user provided a function, it will be called with default value instead of merging.
It can be useful for default values manipulation.
Example: Filter some items from defaults (array) and add 20 to the count default value.
import { defuFn } from "defu";
defuFn(
{
ignore: (val) => val.filter((item) => item !== "dist"),
count: (count) => count + 20,
},
{
ignore: ["node_modules", "dist"],
count: 10,
},
);
Note: if the default value is not defined, the function defined won't be called and kept as value.
Array Function Merger
defuArrayFn
is similar to defuFn
but only applies to array values defined in defaults.
Example: Filter some items from defaults (array) and add 20 to the count default value.
import { defuArrayFn } from 'defu'
defuArrayFn({
ignore: (val) => val.filter(i => i !== 'dist'),
count: () => 20
}, {
ignore: [
'node_modules',
'dist'
],
count: 10
})
Note: the function is called only if the value defined in defaults is an aray.
object
and defaults
are not modified- Nullish values (
null
and undefined
) are skipped. Please use defaults-deep or omit-deep or lodash.defaultsdeep if you need to preserve or different behavior. - Assignment of
__proto__
and constructor
keys will be skipped to prevent security issues with object pollution. - Will concat
array
values (if default property is defined)
console.log(defu({ array: ["b", "c"] }, { array: ["a"] }));
Type
We expose Defu
as a type utility to return a merged type that follows the rules that defu follows.
import type { Defu } from 'defu'
type Options = Defu<{ foo: 'bar' }, [{}, { bar: 'baz' }, { something: 42 }]>
License
MIT. Made with 💖